• Jump To … +
    main.js separate.js single.js web-apg-api.js main.js web-conv-api.js ast.js csv.js dangling-else.js display.js flags.js float.js limits.js main.js multiline-mode.js recursive.js replace.js rules.js split.js testonly.js trace.js udt.js unicode.js web-email.js word-boundaries.js main.js phone-number.js web-main.js web-phone-number.js main.js phone-number.js setup.js translate.js xml.js branch-fail-grammar.js main.js parent-mode-grammar.js setup.js universal-mode-grammar.js colors-app.js colors-callbacks.js colors.js main.js more-app.js more-setup.js more.js ast-callbacks.js bad-input.js basic.js ini-file.js main.js parser-callbacks.js setup.js trace.js anbncn.js and.js c-comment.js compound.js main.js nested.js not.js setup.js boundaries-grammar.js boundaries.js comment-grammar.js comment.js main.js negative-grammar.js negative.js positive-grammar.js positive.js setup.js main.js odata-grammar.js run.js setup.js area-code.js lookaround.js main.js phone-number.js setup.js simple.js all-operators.js default.js fancy-number.js limited-lines.js main.js select-operators.js select-rules.js setup.js main.js minimal.js parent-u.js parent.js phone-number.js setup.js stats.js trace.js universal-u.js universal.js callbacks.js grammar.js main.js parser.js writeHtml.js LICENSE.md README.md index.md
  • run.js

  • §
    /*  *************************************************************************************
     *   copyright: Copyright (c) 2021 Lowell D. Thomas, all rights reserved
     *     license: BSD-2-Clause (https://opensource.org/licenses/BSD-2-Clause)
     *   ********************************************************************************* */
  • §

    This module runs the actual tests.

    module.exports = function valid(testToDo, testIdToTrace) {
      const thisFileName = 'run.js';
    
      /* get the setup data */
      const { utils, odataParser, odataTrace, odataGrammar, tests, map } = require('./setup')();
      let inputString;
      let inputCharacterCodes;
      const outputFile = './output/odata-trace.html';
      let startRule;
      let result;
      let successCount = 0;
      let failCount = 0;
      let totalCount = 0;
    
      /* initialize arrays (to undefined) to count the rules that are tested and touched */
      const rulesTested = [];
      const rulesTouched = [];
      rulesTested.length = odataGrammar.rules.length;
      rulesTouched.length = odataGrammar.rules.length;
    
      /* test all functions that are supposed to succeed */
      const validFunc = function validFunc() {
        tests.valid.forEach((test) => {
          inputString = test.input;
          inputCharacterCodes = utils.stringToChars(inputString);
          startRule = test.rule;
          rulesTested[test.ruleId] = true;
          result = odataParser.parse(odataGrammar, startRule, inputCharacterCodes, { map, rulesTouched, trace: false });
          if (result.success === false) {
            console.log(`valid input test ID ${test.ID} unexpectedly failed`);
            failCount += 1;
          } else {
            successCount += 1;
          }
          totalCount += 1;
        });
      };
    
      /* test all functions that are supposed to fail */
      const invalidFunc = function invalidFunc() {
        tests.invalid.forEach((test) => {
          inputString = test.input;
          inputCharacterCodes = utils.stringToChars(inputString);
          startRule = test.rule;
          rulesTested[test.ruleId] = true;
          result = odataParser.parse(odataGrammar, startRule, inputCharacterCodes, { map, rulesTouched, trace: false });
          if (result.success === false) {
            successCount += 1;
          } else {
            console.log(`invalid input test ID ${test.ID} unexpectedly succeeded`);
            failCount += 1;
          }
          totalCount += 1;
        });
      };
    
      /* display total hits, successes and failures */
      const totals = function totals() {
        console.log(`${totalCount} tests, ${successCount} successful, ${failCount} unsuccessful`);
        let covered = 0;
        rulesTested.forEach((rule) => {
          if (rule) covered += 1;
        });
        let touched = 0;
        rulesTouched.forEach((rule) => {
          if (rule) touched += 1;
        });
        const pctCovered = (covered / rulesTested.length) * 100;
        console.log(`rules total: ${rulesTested.length} rules tested: ${covered} (${pctCovered.toFixed(2)}%)`);
        const pctTouched = (touched / rulesTouched.length) * 100;
        console.log(`rules total: ${rulesTested.length} rules touched: ${touched} (${pctTouched.toFixed(2)}%)`);
      };
      if (testToDo === 'valid') {
        validFunc();
        totals();
      } else if (testToDo === 'invalid') {
        invalidFunc();
        totals();
      } else if (testToDo === 'all') {
        validFunc();
        invalidFunc();
        totals();
      } else if (testToDo === 'trace') {
        /* parse only a single test with tracing. */
        const all = tests.valid.concat(tests.invalid);
        for (let i = 0; i < all.length; i += 1) {
          const test = all[i];
          if (test.ID === testIdToTrace) {
            inputString = test.input;
            inputCharacterCodes = utils.stringToChars(inputString);
            startRule = test.rule;
            console.log(`TRACING test ID: ${test.ID}: ruleId: ${test.ruleId}: rule name: ${test.rule}`);
            if (typeof odataTrace === 'object' && odataTrace.traceObject === 'traceObject') {
              odataParser.trace = odataTrace;
            } else {
              throw new Error(`${thisFileName}valid trace object required`);
            }
            odataParser.parse(odataGrammar, startRule, inputCharacterCodes, { map, rulesTouched, trace: true });
            const html = odataTrace.toHtml('ascii', 'OData', 'OData');
            const fs = require('node:fs');
            fs.writeFileSync(outputFile, html);
            console.log(`TRACE OUTPUT: ${outputFile}`);
            break;
          }
        }
      }
    };